home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 438_01 / stelnet.c < prev    next >
Text File  |  1994-12-19  |  26KB  |  952 lines

  1. /*
  2.  * stelnet - A telnet client for the serial port
  3.  * Version 1.00 (December 20th, 1994)
  4.  *
  5.  * Copyright 1994 Riku Saikkonen (riku.saikkonen@pcb.compart.fi)
  6.  *
  7.  * This program is free software; you can redistribute and/or modify it
  8.  * under the terms of the GNU General Public License version 2 as published
  9.  * by the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful, but
  12.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
  14.  * Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License along
  17.  * with this program (as the file COPYING); if not, write to the Free
  18.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  * The author, Riku Saikkonen, can be contacted via the following means:
  21.  * E-mail: riku.saikkonen@pcb.compart.fi (preferred) or
  22.  *         risaikko@freenet.hut.fi
  23.  * Paper mail: Riku Saikkonen
  24.  *             Alakartanontie 4 B 63
  25.  *             SF-02360  ESPOO
  26.  *             Finland
  27.  */
  28.  
  29. /*
  30.  * Known bugs:
  31.  * ZModem ZR[Q]INIT to telnet without a reply activates ZModem 8-bit clean
  32.  *   mode (ZDLE ZDLE exits it)
  33.  *
  34.  * Todo list:
  35.  * user-selectable terminal types
  36.  * don't beep on local screen in put_ser() (affects only warnings etc.)
  37.  * debug mode (show IACs)
  38.  * ECHO option (local echo)
  39.  * TELNET options 5 (STATUS), 32-38?
  40.  * non-SGA mode + send Go Ahead command
  41.  * telnet handshaking (how?)
  42.  * telnet/serial options in synchronisation with sob/tob
  43.  *   (difficult, not very useful)
  44.  */
  45.  
  46. #include <stdio.h>
  47. #include <conio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <ctype.h>
  51. #include <dos.h>
  52. #include <time.h>
  53. #include <tcp.h>
  54.  
  55. #define BANNER "stelnet 1.00"
  56. #define COPYRIGHT1 \
  57.   "Copyright 1994 Riku Saikkonen (riku.saikkonen@pcb.compart.fi)"
  58. #define COPYRIGHT2 \
  59.   "stelnet is free software, distributed under the terms of the GNU " \
  60.     "General\r\n" \
  61.   "Public License version 2, and comes with ABSOLUTELY NO WARRANTY; for " \
  62.     "details,\r\n" \
  63.   "see the documentation distributed with the program.\r\n"
  64.  
  65. /* Default telnet, serial buffer sizes (override with makefile) */
  66. #ifndef TIBLEN
  67. #define TIBLEN 512
  68. #endif
  69. #ifndef SIBLEN
  70. #define SIBLEN 512
  71. #endif
  72. #ifndef TOBLEN
  73. #define TOBLEN 8192
  74. #endif
  75. #ifndef SOBLEN
  76. #define SOBLEN 8192
  77. #endif
  78. #ifndef SOBLIMIT
  79. #define SOBLIMIT 512
  80. #endif
  81.  
  82. /* Default loopcheck value (override with makefile) */
  83. #ifndef LOOPCHECK
  84. #define LOOPCHECK 100
  85. #endif
  86.  
  87. typedef unsigned char BYTE;
  88. typedef unsigned int  WORD;
  89.  
  90. #define SE 240
  91. #define BRK 243
  92. #define IP 244
  93. #define AO 245
  94. #define AYT 246
  95. #define EC 247
  96. #define EL 248
  97. #define SB 250
  98. #define WILL 251
  99. #define WONT 252
  100. #define DO 253
  101. #define DONT 254
  102. #define IAC 255
  103.  
  104. #define IS 0
  105. #define SEND 1
  106.  
  107. #define TELOPT_BINARY 0
  108. #define TELOPT_ECHO 1
  109. #define TELOPT_SGA 3
  110. #define TELOPT_TTYPE 24
  111.  
  112. #define addsob(c) { if (sobp>=SOBLEN) sobp=0; /* Wrap */ \
  113.     if (sobp==sobs && sobp!=0) \
  114.       {sobs++;soverrun++;} /* Buffer overrun; lose first character */ \
  115.     sob[sobp]=c;sobp++; }
  116.  
  117. #define addtob(c) { if (tobp>=TOBLEN) tobp=0; /* Wrap */ \
  118.     if (tobp==tobs && tobp!=0) \
  119.       {tobs++;toverrun++;} /* Buffer overrun; lose first character */ \
  120.     tob[tobp]=c;tobp++; }
  121.  
  122. #define putstr(s) {fputs(s,stdout);}
  123.  
  124. void syntax(void);
  125.  
  126. int init_tel(void);
  127. void deinit_tel(void);
  128. #define ok_tel() tcp_tick(socket)
  129. #define read_tel(buf,sz) sock_fastread(socket,buf,sz)
  130. #define write_tel(buf,sz) sock_fastwrite(socket,buf,sz)
  131.  
  132. int init_ser(void);
  133. int read_ser(BYTE *buf, int sz);
  134. int write_ser(BYTE *buf, int sz);
  135. int ok_ser(void);
  136. int put_ser(char *s);
  137. void deinit_ser(void);
  138.  
  139. int comport;
  140. union REGS reg;
  141. struct SREGS sreg;
  142.  
  143. char hostname[128];
  144. int port;
  145. unsigned long hostnum;
  146. tcp_Socket *socket;
  147. tcp_Socket socketdata;
  148.  
  149. int opt_bin;
  150. int copt_cd,copt_localscr,copt_idle,copt_sendinit,copt_8bit;
  151. char copt_username[30];
  152.  
  153. int main(int argc, char *argv[])
  154. {
  155.   static BYTE tib[TIBLEN],tob[TOBLEN];
  156.   static BYTE sib[SIBLEN],sob[SOBLEN];
  157.   BYTE sibc,tibc;
  158.   static FILE *fp;
  159.   int sobs,sobp,tobs,tobp,sibend,tibend;
  160.   int i,j;
  161.   unsigned u=0;
  162.   int sercmd,teliac,quit,timewarn,itimewarn;
  163.   time_t stime,etime,itime,curtime;
  164.   unsigned char sercmdkey;
  165.   long soverrun,toverrun;
  166.   int clean8bit,clean8bitz,zmframe;
  167.   int loopcount,loop2count,notidle;
  168.   static char s[256],exit8bits[11]="-\030\030stelnet";
  169.  
  170.   putstr(BANNER "\n" COPYRIGHT1 "\n" COPYRIGHT2 "\n");
  171.  
  172.   if (argc<4) syntax();
  173.  
  174.   comport=atoi(argv[1]);
  175.   if (comport<1 || comport>8)
  176.   {
  177.     putstr("Invalid COM port!\n");
  178.     exit(10);
  179.   }
  180.   comport--;
  181.  
  182.   itime=etime=0;
  183.   copt_cd=copt_sendinit=1;copt_localscr=copt_idle=copt_8bit=0;
  184.   itimewarn=timewarn=0;
  185.   strcpy(copt_username,"Unknown");
  186.   stime=time(NULL);
  187.   sercmdkey=255;
  188.  
  189.   for (i=4;i<argc;i++)
  190.   {
  191.     switch (tolower(argv[i][0]))
  192.     {
  193.       case 'i':
  194.         copt_idle=1;
  195.         putstr("Idle timeout checking on.\n");
  196.         break;
  197.       case 't':
  198.         timewarn=atoi(&argv[i][1]);
  199.         etime=stime+timewarn*60;
  200.         timewarn=300;
  201.         putstr("Time limit set.\n");
  202.         break;
  203.       case '8': copt_8bit=1;putstr("8-bit clean mode.\n");break;
  204.       case 'e':
  205.         sercmdkey=atoi(&argv[i][1]);
  206.         sprintf(s,"Escape character set to ASCII %d.\n",sercmdkey);
  207.         putstr(s);
  208.         break;
  209.       case 'c': copt_cd=0;putstr("Carrier Detect checking off.\n");break;
  210.       case 'l': copt_localscr=1;putstr("Local screen on.\n");break;
  211.       case 'x':
  212.         copt_sendinit=0;putstr("Not sending initialisation codes.\n");
  213.         break;
  214.       case 'd': /* Door information file */
  215.         if ((fp=fopen(&argv[i][2],"rb"))==NULL)
  216.         {
  217.           putstr("Error opening door information file!\n");
  218.           exit(9);
  219.         }
  220.         switch (tolower(argv[i][1]))
  221.         {
  222.           case 'p': /* PCBOARD.SYS */
  223.             fseek(fp,84,SEEK_SET);
  224.             fread(copt_username,sizeof(unsigned char),25,fp);
  225.             copt_username[25]=0; /* Purge spaces from right !!! */
  226.             fread(&u,sizeof(unsigned int),1,fp);
  227.             if (u<1440) /* !!! */
  228.             {
  229.               etime=stime+u*60;
  230.               timewarn=300;
  231.             }
  232.             putstr("PCBOARD.SYS read.\n");
  233.             break;
  234.           default: syntax();
  235.         }
  236.         fclose(fp);
  237.         break;
  238.       default: syntax();
  239.     }
  240.   }
  241.  
  242.   if (init_ser()<0)
  243.   {
  244.     putstr("Error initialising serial port!\n");
  245.     exit(3);
  246.   }
  247.  
  248.   /* VT-100: ESC c (reset), ESC [1;1f (home), ESC [2J (clear screen) */
  249.   if (copt_sendinit) put_ser("\033c\033[1;1f\033[2J");
  250.  
  251.   put_ser("\r\n" BANNER "\r\n" COPYRIGHT1 "\r\n" COPYRIGHT2 "\r\n");
  252.  
  253.   sprintf(s,"Serial escape character is ASCII %d.\r\n",sercmdkey);
  254.   putstr(s);
  255.  
  256.   if (copt_8bit)
  257.     put_ser("In 8-bit clean mode; exit with '<255><^X><^X>stelnet'.\r\n");
  258.  
  259.   if (etime!=0)
  260.   {
  261.     sprintf(s,"Time left: %.1f min\r\n",(etime-time(NULL))/60.0);
  262.     put_ser(s);
  263.   }
  264.  
  265.   strcpy(hostname,argv[2]);
  266.   port=atoi(argv[3]);
  267.  
  268.   sprintf(s,"\r\nTrying to connect to %s port %d...\r\n",hostname,port);
  269.   put_ser(s);
  270.  
  271.   i=init_tel();
  272.   if (i<0)
  273.   {
  274.     if (i==-1) put_ser("Connection refused.");
  275.     else put_ser("Name resolver not working!");
  276.     put_ser(" Exiting.\r\n");
  277.     deinit_ser();
  278.     if (i==-1) exit(2); else exit(4);
  279.   }
  280.  
  281.   put_ser("Connected. Type <ASCII 255> ? for a list of commands.\r\n");
  282.  
  283.   sobs=sobp=tobs=tobp=sercmd=teliac=quit=0;
  284.   soverrun=toverrun=0;
  285.   zmframe=clean8bitz=0;
  286.   clean8bit=copt_8bit;
  287.   sibc=tibc=0;
  288.   loopcount=loop2count=notidle=1;
  289.   itimewarn=6;
  290.  
  291.   /* Telnet initialisation IACs */
  292.   if (copt_sendinit)
  293.   {
  294.     tob[0]=IAC;tob[1]=DO;tob[2]=TELOPT_BINARY;
  295.     tob[3]=IAC;tob[4]=WILL;tob[5]=TELOPT_BINARY;opt_bin=1;
  296.     tob[6]=IAC;tob[7]=DO;tob[8]=TELOPT_ECHO;
  297.     tob[9]=IAC;tob[10]=WILL;tob[11]=TELOPT_SGA;
  298.     tob[12]=IAC;tob[13]=DO;tob[14]=TELOPT_SGA;
  299.     tob[15]=IAC;tob[16]=WILL;tob[17]=TELO